#include <cstdlib>
#include <stdio.h>

extern "C"{
#include <libavutil/pixfmt.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
}

#include <string>
using std::string;

int testAVIO(){
    AVFormatContext * pFmtCtx=avformat_alloc_context();
    if(pFmtCtx==nullptr){
        return EXIT_FAILURE;
    }

    printf("=========textAVIO()===========\n");
    AVInputFormat * pInstance=nullptr;
    //string url("rtsp://admin:admin@192.168.5.100/live/chn=1");
    string url("rtmp://192.168.5.100:1935/hlsram/live0");

    if(avformat_open_input(&pFmtCtx, url.data(), pInstance,nullptr)){
        printf("avformat open failed\n");
        goto quit;
    }
    else {
        printf("open stream success\n");
    }
    printf("%s:%d\n",__FILE__,__LINE__);

    if(avformat_find_stream_info(pFmtCtx,nullptr)<0){
        printf("av_find_stream_info error\n");
        goto quit;
    }
    else{
        printf("av_find_stream_info success\n");
        printf("nb_streams:%d\n",pFmtCtx->nb_streams);
    }

quit:
        avformat_close_input(&pFmtCtx);
        avformat_free_context(pFmtCtx);

        return 0;
}

int read_packet(void * ptr,uint8_t * buf,int buf_size){
    static int total=0;
    FILE * fp=(FILE *)ptr;
    int sz=fread(buf,1,buf_size,fp);
    total+=sz;
    printf("Read %d bytes,total:%d\n",sz,total);
    return sz;
}

int64_t seek_func(void * opaque,int64_t offset,int whence){
    int64_t ret=0;
    FILE * fp=(FILE*)opaque;
    if(whence==AVSEEK_SIZE){
        fseek(fp,0,SEEK_END);
        int64_t size=ftell(fp);
        fseek(fp,0,SEEK_SET);
        return size;
    }

    if(fseek(fp,offset,whence)!=0){
        return -1;
    }

    return ftell(fp);
    //fseek(fp,offset,whence);
    //ret=ftell(fp);
    //printf("ftell pos:%ld\n",ret);
    //return ret;
}

int testAVIO2(){
    printf("===============\n");
    FILE * fp=fopen("videos/ac_wlh480.mp4","rb");
    if(fp==nullptr){
        printf("open file error\n");
        return EXIT_FAILURE;
    }

    int size=32768;
    unsigned char * pbuff=(unsigned char *)malloc(size);

    AVIOContext * pIOCtx=avio_alloc_context(pbuff,size,0,fp,read_packet,0,seek_func);
    printf("avio_alloc_context end\n");

    AVFormatContext * pFmtCtx=avformat_alloc_context();
    if(pFmtCtx==nullptr){
        printf("avformat_alloc_context error\n");
        return EXIT_FAILURE;
    }

    printf("avformat_alloc_context end\n");
    pFmtCtx->pb=pIOCtx;
    pFmtCtx->flags=AVFMT_FLAG_CUSTOM_IO;

    printf("%s:%d\n",__FUNCTION__,__LINE__);
    AVInputFormat * pInstance=av_find_input_format("mp4");
    int ret;
    ret=avformat_open_input(&pFmtCtx,"",pInstance,nullptr);
    printf("ret:%d\n",ret);
    if(ret<0){
        printf("avformat_open_input error\n");
        goto quit;
    }
    else{
        printf("open stream success\n");
    }

    if(avformat_find_stream_info(pFmtCtx,nullptr)<0){
        printf("avformat_find_stream_info error\n");
        goto quit;
    }
    else{
        printf("avformat_find_stream_info success\n");
        printf("nb_streams:%d\n",pFmtCtx->nb_streams);
    }

quit:
    avformat_close_input(&pFmtCtx);
    avformat_free_context(pFmtCtx);
    free(pbuff);

    return 0;
}


int main(){
    //int a=testAVIO2();
    testAVIO2();
    return 0;
}
